package cz.data.auth.config;

import cz.data.common.base.BaseResponse;
import cz.data.common.exception.AuthException;
import cz.data.common.exception.DataException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(DataException.class)
    public BaseResponse handleWithException(DataException e) {
        log.error(String.format("自定义异常信息 ex=%s", e.getMessage()), e);
        return BaseResponse.error(500, e.getMessage());
    }

    /**
     * 请求的 JSON 参数在请求体内的参数校验
     */
    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    public BaseResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        String message = StringUtils.collectionToCommaDelimitedString(
                e.getBindingResult().getFieldErrors()
                        .stream()
                        .map(FieldError::getDefaultMessage)
                        .collect(Collectors.toList()));
        log.error("参数校验异常信息 ex={}", e.getMessage());
        return BaseResponse.error(500, message);
    }

    /**
     * 请求的 URL 参数检验
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public BaseResponse handleConstraintViolationException(ConstraintViolationException e) {
        String message = StringUtils.collectionToCommaDelimitedString(
                e.getConstraintViolations()
                        .stream()
                        .map(ConstraintViolation::getMessage)
                        .collect(Collectors.toList()));
        log.error("参数校验异常信息 ex={}", e.getMessage());
        return BaseResponse.error(500, message);
    }

    @ExceptionHandler(Exception.class)
    public BaseResponse handleException(Exception e) {
        log.error(String.format("自定义异常信息 ex=%s", e.getMessage()), e);
        return BaseResponse.error(500, e.getMessage());
    }

    @ExceptionHandler(AuthException.class)
    public BaseResponse handleAuthException(AuthException e) {
        log.warn(String.format("认证失败: %s", e.getMessage()));
        return BaseResponse.error(401, e.getMessage());
    }
}